package com.swgk.core;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import com.swgk.core.base.model.entity.BehaviourFlowLog;
import com.swgk.core.dialog.DialogHelper;
import com.swgk.core.mmkvutil.CacheMarker;
import com.swgk.core.mmkvutil.MkvUtils;
import com.swgk.core.util.DateUtils;
import com.swgk.core.util.MLog;
import java.util.Calendar;
import java.util.Date;

/**
 * @author 张驰
 * @date 2021/7/16 14:24
 * @Description 统计app模块使用时长和次数
 * @name com.sgb.kjwl.api
 */
public class ActivityLifeCycle implements Application.ActivityLifecycleCallbacks {

    /**
     * 上次检查时间，用于在运行时作为基准获取用户时间
     */
    public static long lastCheckTime = 0;
    public static long startCheckTime = 0;//用户进入app的时间
    /** 前台Activity数量 **/
    private int foregroundActivityCount = 0;
    /**
     * Activity是否在修改配置，
     */
    private boolean isChangingConfigActivity = false;
    /**
     *  应用将要切换到前台
     */
    private boolean willSwitchToForeground = false;
    /**
     * 当前是否在前台
     */
    private boolean isForegroundNow = false;
    /**
     * 上次暂停的Activity信息
     */
    private String lastPausedActivityName;
    private int lastPausedActivityHashCode;
    private long lastPausedTime;
    private long appUseReduceTime = 0;
    /**
     *  每次有Activity启动时的开始时间点
     */
    private long appStartTime = 0L;

    /**
     * 本次统计时，运行的时间
     */
    private long runTimeThisDay = 0L;
    private FlowLogUtils flowLogUtils;
    private boolean aBoolean;
    private Activity mActivity;

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        MLog.d("onActivityCreated " +  getActivityName(activity));
        aBoolean = MkvUtils.get().getBoolean(MkvUtils.CommomData, CacheMarker.PrivacyAgreement, false);
        if (aBoolean){
            flowLogUtils = new FlowLogUtils();
        }
        mActivity = activity;
    }

    @Override
    public void onActivityStarted(Activity activity) {
        MLog.d("onActivityStarted "+ getActivityName(activity) + " " + foregroundActivityCount);
        if (aBoolean){
            //前台没有Activity，说明新启动或者将从从后台恢复
            if (foregroundActivityCount == 0 || !isForegroundNow) {
                willSwitchToForeground = true;
            }else {
                //应用已经在前台，此时保存今日运行的时间。
                runTimeThisDay  = System.currentTimeMillis() - appStartTime;
                lastCheckTime = System.currentTimeMillis();
                saveTodayPlayTime(activity, runTimeThisDay);
            }
            appStartTime = System.currentTimeMillis();
            if (isChangingConfigActivity) {
                isChangingConfigActivity = false;
                return;
            }
            foregroundActivityCount += 1;
        }
    }

    @Override
    public void onActivityResumed(Activity activity) {
        if (this.mActivity == null){
            this.mActivity = activity;
        }
        MLog.d("onActivityResumed  " + getActivityName(activity));
        if (aBoolean){
            long entTime = lastCheckTime;
            //在这里更新检查时间点，是为了保证从后台恢复到前台，持续计时的准确性。
            lastCheckTime = System.currentTimeMillis();
            addAppUseReduceTimeIfNeeded(activity);
            if (willSwitchToForeground && isInteractive(activity)) {
                isForegroundNow = true;
                MLog.d( "switch to foreground");
                startCheckTime = System.currentTimeMillis();
            }
            if (isForegroundNow) {
                willSwitchToForeground = false;
            }
        }
    }

    @Override
    public void onActivityPaused(Activity activity) {
        this.mActivity = null;
        MLog.d("onActivityPaused " + getActivityName(activity));
        if (aBoolean){
            lastPausedActivityName = getActivityName(activity);
            lastPausedActivityHashCode = activity.hashCode();
            lastPausedTime = System.currentTimeMillis();
        }
    }

    @Override
    public void onActivityStopped(Activity activity) {
        MLog.d("onActivityStopped" + getActivityName(activity));
        if (aBoolean){
            addAppUseReduceTimeIfNeeded(activity);
            //如果这个Activity实在修改配置，如旋转等，则不保存时间直接返回
            if (activity.isChangingConfigurations()) {
                isChangingConfigActivity = true;
                return;
            }
            //该Activity要进入后台，前台Activity数量-1。
            foregroundActivityCount -= 1;
            //当前已经是最后的一个Activity，代表此时应用退出了，保存时间。
            // 如果跨天了，则从新一天的0点开始计时
            if (foregroundActivityCount == 0) {
                isForegroundNow = false;
                MLog.d("switch to background (reduce time[" + appUseReduceTime + "])");
                if (getTodayStartTime() > appStartTime){
                    runTimeThisDay = System.currentTimeMillis() - getTodayStartTime();
                }else {
                    runTimeThisDay = System.currentTimeMillis() - appStartTime;
                }
                saveTodayPlayTime(activity, runTimeThisDay);
                lastCheckTime = System.currentTimeMillis();
                MLog.d("run time  :"  + runTimeThisDay);
                switchToBackground(getActivityName(activity),startCheckTime,lastCheckTime);
            }
        }
    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
        MLog.d("onActivitySaveInstanceState  " + getActivityName(activity));
    }

    @Override
    public void onActivityDestroyed(Activity activity) {
        MLog.d("onActivityDestroyed  " + getActivityName(activity));
        if (aBoolean){
            if (getActivityName(activity).contains("WelcomeActivity")){
                startCheckTime = System.currentTimeMillis();
                //app当天第一次打开
                isfirstAppStart();
                isAppStart();
            }
        }
    }

    private void addAppUseReduceTimeIfNeeded(Activity activity) {
        if (getActivityName(activity).equals(lastPausedActivityName) && activity.hashCode() == lastPausedActivityHashCode) {
            long now = System.currentTimeMillis();
            if (now - lastPausedTime > 1000) {
                appUseReduceTime += now - lastPausedTime;
            }
        }
        lastPausedActivityHashCode = -1;
        lastPausedActivityName = null;
        lastPausedTime = 0;
    }

    private boolean isInteractive(Context context) {
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
            return pm.isInteractive();
        } else {
            return pm.isScreenOn();
        }
    }

    private String getActivityName(final Activity activity) {
        return activity.getClass().getCanonicalName();
    }

    /**
     * 获取今日0点的时间点，/1000*1000保证每次取值相同。
     * @return
     */
    private long getTodayStartTime(){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        long time = calendar.getTimeInMillis()/1000*1000;
        return time;
    }

    /**
     * 保存今日运行时间，以今日0点的时间作为Key值。
     * @param context
     * @param time
     */
    private void saveTodayPlayTime(Context context, long time){
        long todayTime = MkvUtils.get().getLong(MkvUtils.CommomData, MkvUtils.upDateTotalTime, 0);
        MLog.d("today :" + String.valueOf(getTodayStartTime()) + " : time : " + todayTime);
        MLog.d("today totalTime:" +time +" :" + (todayTime + time));
        MkvUtils.get().putLong(MkvUtils.CommomData,MkvUtils.upDateTotalTime, todayTime+time);
    }

    /**
     * app当天第一次打开
     * 每天只调一次
     */
    private void isfirstAppStart() {
        long timeNew = System.currentTimeMillis();
        long timeOld = MkvUtils.get().getLong(MkvUtils.CommomData, MkvUtils.upDateTodayTime, 0);
        if (!DateUtils.timestampToDate(timeNew).equals(DateUtils.timestampToDate(timeOld))){
            MkvUtils.get().putLong(MkvUtils.CommomData,MkvUtils.upDateTotalTime, 0); //将app总时长清空
            BehaviourFlowLog behaviourFlowLog = new BehaviourFlowLog(
                    "WelcomeActivity",
                    "DAU",
                    "WelcomeActivity用户当天首次运行",
                    "jyb");
            flowLogUtils.getFlowLog(behaviourFlowLog);
        }
    }

    /**
     * app启动次数
     */
    private void isAppStart() {
        BehaviourFlowLog behaviourFlowLog = new BehaviourFlowLog(
                "WelcomeActivity",
                "START_NUM",
                "应用重新启动上报启动次数,发生的界面 WelcomeActivity",
                "jyb");
        flowLogUtils.getFlowLog(behaviourFlowLog);
    }

    /**
     * app再前台
     * @param startActivityName 统计开始时，发生的界面
     * @param startTime 统计开始的时间
     * @param endTime 统计开始时，上次暂停的时间
     * @param duration 统计开始时，已经使用时长
     */
    private void switchToForeground(String startActivityName,long startTime,long endTime,long duration) {
        BehaviourFlowLog behaviourFlowLog = new BehaviourFlowLog(
                startActivityName,
                "USE_TIME",
                "app切换到前台，统计开始时，" +
                        "发生的界面" + startActivityName +
                        ",统计开始的时间 startTime:" + startTime +
                        ", 统计开始时，上次暂停的时间 endTime:" + endTime +
                        ",统计开始时，已经使用时长duration:" + duration,
                "jyb");
        behaviourFlowLog.getExtra().getTarget().setStartTime(startTime);
        behaviourFlowLog.getExtra().getTarget().setEndTime(endTime);
        behaviourFlowLog.getExtra().getTarget().setDuration(duration);
        if (startTime == behaviourFlowLog.getWhen()) return;//当本次启动时间和当前调用时间相同时，本次切换调用无效
        flowLogUtils.getFlowLog(behaviourFlowLog);
    }

    /**
     * 切换到后台
     * @param startTime 本次使用开始时间
     * @param endTime 本次使用结束时间
     */
    private void switchToBackground(String entActivityName,long startTime,long endTime) {
        if(startTime == 0){
            startTime = System.currentTimeMillis();
        }
        //使用时长
        long duration = endTime - startTime;
        if (duration < 5000) return;
        BehaviourFlowLog behaviourFlowLog = new BehaviourFlowLog(
                entActivityName,
                "USE_TIME",
                "app切换到后台，统计结束时，" +
                        "发生的界面" + entActivityName +
                        ",统计结束时 本次开始时间startTime:" + startTime +
                        ", 统计结束时，本次结束时 endTime:" + endTime +
                        ",统计结束时，本次app打开总共使用时间 duration :" + duration ,
                "jyb-app");
        behaviourFlowLog.getExtra().getTarget().setStartTime(startTime);
        behaviourFlowLog.getExtra().getTarget().setEndTime(endTime);
        behaviourFlowLog.getExtra().getTarget().setDuration(duration);
        flowLogUtils.getFlowLog(behaviourFlowLog);
    }

    /**
     *
     * @return
     */
    public Activity getActivity(){
        return mActivity;
    }

}
